import 'dart:async';

import 'package:flutter/material.dart';
import 'package:top_foundation/utils/theme/theme.dart';
import 'package:whale/helper/utils/util.dart';

class MarqueeGiftView extends StatefulWidget {
  const MarqueeGiftView({
    super.key,
    required this.itemBuilder,
    required this.itemCount,
  });
  final IndexedWidgetBuilder itemBuilder;
  final int itemCount;

  @override
  State<MarqueeGiftView> createState() => _MarqueeViewState();
}

class _MarqueeViewState extends State<MarqueeGiftView> {
  final sc = ScrollController();
  int index = 0;
  late Timer timer;
  List<MarqueeModel> list = [];
  final double height = (36.r).floorToDouble();
  @override
  initState() {
    super.initState();
    setupData();
    firstRun();
    timer = Timer.periodic(const Duration(seconds: 5), (timer) async {
      run();
    });
  }

  void run() async {
    if (list.isEmpty || sc.positions.isEmpty || !mounted) {
      return;
    }
    index++;
    final off = index * height;
    if (sc.position.maxScrollExtent < off) {
      return;
    }
    await sc.animateTo(index * height,
        duration: const Duration(milliseconds: 500), curve: Curves.easeInOut);

    await Future.delayed(const Duration(seconds: 2));
    await list[index].scrollToBottom();

    if (index > 1) {
      list[index - 1].sc?.jumpTo(0);
    }
    if (index >= list.length - 1) {
      index = 0;
      sc.jumpTo(0);
      await Future.delayed(const Duration(milliseconds: 200));
      list.last.sc?.jumpTo(0);
    }
  }

  void firstRun() async {
    Future.delayed(Duration(seconds: 2)).then((value) {
      list[0].scrollToBottom();
    });
  }

  @override
  void didUpdateWidget(covariant MarqueeGiftView oldWidget) {
    setupData();
    super.didUpdateWidget(oldWidget);
  }

  void setupData() {
    if (widget.itemCount <= 0) {
      return;
    }
    list = List.generate(widget.itemCount + 1, (index) => MarqueeModel());
  }

  @override
  void dispose() {
    timer.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(top: 17.r, bottom: 8.r),
      width: 270.w,
      height: height,
      child: ListView.builder(
        controller: sc,
        physics: const NeverScrollableScrollPhysics(),
        padding: EdgeInsets.zero,
        itemBuilder: (context, index) {
          final m = list[index];
          return _HorizontalGiftText(
            height: height,
            model: m,
            itemBuilder: (ctx) => widget.itemBuilder(ctx, index),
          );
        },
        itemCount: list.length,
      ),
    );
  }
}

class _HorizontalGiftText extends StatefulWidget {
  const _HorizontalGiftText({
    this.height,
    required this.model,
    required this.itemBuilder,
  });
  final double? height;
  final MarqueeModel model;
  final WidgetBuilder itemBuilder;

  @override
  State<_HorizontalGiftText> createState() => __HorizontalGiftTextState();
}

class __HorizontalGiftTextState extends State<_HorizontalGiftText> {
  final sc = ScrollController();

  @override
  void initState() {
    widget.model.sc = sc;
    super.initState();
  }

  @override
  void dispose() {
    widget.model.sc = null;
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 270.w,
      alignment: Alignment.centerLeft,
      height: widget.height,
      padding: EdgeInsets.symmetric(horizontal: 10.r),
      decoration: BoxDecoration(
          color: ITheme.themeColor.withAlpha(40),
          borderRadius: BorderRadius.circular(8.r)),
      child: SingleChildScrollView(
        controller: sc,
        scrollDirection: Axis.horizontal,
        child: widget.itemBuilder(context),
      ),
    );
  }
}

class MarqueeModel {
  ScrollController? sc;
  Future<void> scrollToBottom() async {
    if (sc == null || sc?.positions.isNotEmpty != true) return;

    if (sc!.position.maxScrollExtent > 0) {
      await sc!.animateTo(sc!.position.maxScrollExtent,
          duration: Duration(
              milliseconds: (sc!.position.maxScrollExtent * 8).floor()),
          curve: Curves.linear);
    }
  }

  MarqueeModel();

  factory MarqueeModel.copy(MarqueeModel b) {
    return MarqueeModel();
  }
}
